#include <stdio.h>
#include <string.h>
//#include "cmsis_os.h"
#include "stm32wlxx_hal.h"
#include "bme68x_function.h"
#include "bme68x.h"
#include "main.h"

//struct bme68x_dev bme68xdev;
static uint8_t dev_addr;
uint8_t GTXBuffer[512], GRXBuffer[2048];
extern I2C_HandleTypeDef hi2c2;
#define I2C_HANDLE	(hi2c2)
//extern relevant_data_s rest_data;

void bmeb8x_delay_us(uint32_t period, void *intf_ptr)
{
	uint32_t i;

	while(period--)
	{
		for(i = 0; i < 84; i++)
		{
			;
		}
	}
}

void bme68x_check_rslt(const char api_name[], int8_t rslt)
{
    switch (rslt)
    {
        case BME68X_OK:

            /* Do nothing */
            break;
        case BME68X_E_NULL_PTR:
            //PDEBUG("API name [%s]  Error [%d] : Null pointer\r\n", api_name, rslt);
            break;
        case BME68X_E_COM_FAIL:
            //PDEBUG("API name [%s]  Error [%d] : Communication failure\r\n", api_name, rslt);
            break;
        case BME68X_E_INVALID_LENGTH:
            //PDEBUG("API name [%s]  Error [%d] : Incorrect length parameter\r\n", api_name, rslt);
            break;
        case BME68X_E_DEV_NOT_FOUND:
            //PDEBUG("API name [%s]  Error [%d] : Device not found\r\n", api_name, rslt);
            break;
        case BME68X_E_SELF_TEST:
            //PDEBUG("API name [%s]  Error [%d] : Self test error\r\n", api_name, rslt);
            break;
        case BME68X_W_NO_NEW_DATA:
            //PDEBUG("API name [%s]  Warning [%d] : No new data found\r\n", api_name, rslt);
            break;
        default:
            //PDEBUG("API name [%s]  Error [%d] : Unknown error code\r\n", api_name, rslt);
            break;
    }
}


int8_t BME68X_Set_ForcedMode(struct bme68x_dev *dev)
{
	int8_t rslt;
	struct bme68x_conf conf;
	struct bme68x_heatr_conf heatr_conf;

	/* Check if rslt == BME68X_OK, report or handle if otherwise */
	conf.filter = BME68X_FILTER_OFF;
	conf.odr = BME68X_ODR_NONE;
	conf.os_hum = BME68X_OS_16X;
	conf.os_pres = BME68X_OS_1X;
	conf.os_temp = BME68X_OS_2X;
	rslt = bme68x_set_conf(&conf, dev);
	bme68x_check_rslt("bme68x_set_conf", rslt);

	/* Check if rslt == BME68X_OK, report or handle if otherwise */
	heatr_conf.enable = BME68X_ENABLE;
	heatr_conf.heatr_temp = 300;
	heatr_conf.heatr_dur = 100;
	rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, dev);
	bme68x_check_rslt("bme68x_set_heatr_conf", rslt);
	
	return rslt;
}
struct bme68x_data data;
uint32_t tmp_data;
uint8_t lora_data[23];
int8_t BME68X_Get_Sensordata(struct bme68x_dev *dev)
{
	int8_t rslt;
	struct bme68x_conf conf;
	struct bme68x_heatr_conf heatr_conf;
//	struct bme68x_data data;
	uint8_t n_fields;
	uint32_t del_period;
	uint32_t time_ms = 0;

	rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, dev);
	bme68x_check_rslt("bme68x_set_op_mode", rslt);

	/* Calculate delay period in microseconds */
	del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, dev) + (heatr_conf.heatr_dur * 1000);
	dev->delay_us(del_period, dev->intf_ptr);

	time_ms = HAL_GetTick()/1000;

	/* Check if rslt == BME68X_OK, report or handle if otherwise */
	rslt = bme68x_get_data(BME68X_FORCED_MODE, &data, &n_fields, dev);
	bme68x_check_rslt("bme68x_get_data", rslt);

//	sprintf(rest_data.temperature,"%.1f",data.temperature);
//	sprintf(rest_data.pressure,"%.1f",data.pressure);
//	sprintf(rest_data.humidity,"%.1f",data.humidity);
//	sprintf(rest_data.gasres,"%.1f",data.gas_resistance);
	return rslt;
}

BME68X_INTF_RET_TYPE SensorAPI_I2Cx_Read(uint8_t subaddress, uint8_t *pBuffer, uint32_t ReadNumbr, void *intf_ptr)
{
	uint8_t dev_addr = *(uint8_t*)intf_ptr;
	uint16_t DevAddress = dev_addr << 1;

	// send register address
	HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, &subaddress, 1, BUS_TIMEOUT);
	HAL_I2C_Master_Receive(&I2C_HANDLE, DevAddress, pBuffer, ReadNumbr, BUS_TIMEOUT);
	return 0;
}

BME68X_INTF_RET_TYPE SensorAPI_I2Cx_Write(uint8_t subaddress, const uint8_t *pBuffer, uint32_t WriteNumbr, void *intf_ptr)
{
	uint8_t dev_addr = *(uint8_t*)intf_ptr;
	uint16_t DevAddress = dev_addr << 1;

	GTXBuffer[0] = subaddress;
	memcpy(&GTXBuffer[1], pBuffer, WriteNumbr);

	// send register address
	HAL_I2C_Master_Transmit(&I2C_HANDLE, DevAddress, GTXBuffer, WriteNumbr+1, BUS_TIMEOUT);
	return 0;
}

int8_t Init_BME68X(struct bme68x_dev *dev)
{
	int8_t rslt = BME68X_OK;
	
#if defined(USE_I2C_INTERFACE)
//	PDEBUG("I2C Interface\n");
	dev_addr = BME68X_I2C_ADDR_LOW;
	dev->intf = BME68X_I2C_INTF;
	dev->read = SensorAPI_I2Cx_Read;
	dev->write = SensorAPI_I2Cx_Write;
#elif defined(USE_SPI_INTERFACE)
	PDEBUG("SPI Interface\n");
	dev->intf = BME68X_SPI_INTF;
	dev->read = SensorAPI_SPIx_Read;
	dev->write = SensorAPI_SPIx_Write;
#endif
	dev->delay_us = bmeb8x_delay_us;
	dev->intf_ptr = &dev_addr;
	dev->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */

	bme68x_soft_reset(dev);
	dev->delay_us(10, dev->intf_ptr);
	
	rslt = bme68x_init(dev);
	if(rslt != BME68X_OK)
	{
		//PDEBUG("bme68x_init failed, rslt=%d\r\n", rslt);
	}
	else
	{
		//PDEBUG("bme68x_init successful, chip id=0x%02X\r\n", dev->chip_id);
	}

	rslt = BME68X_Set_ForcedMode(dev);
	if(rslt != BME68X_OK)
	{
		//PDEBUG("BME68X_Set_ForcedMode failed, rslt=%d\r\n", rslt);
	}
	
	return rslt;
}



